extends ../templates/main.jade

block title
  | C | Language Criticism | xigoi

block content
  h1 C Language Criticism
  p.disclaimer I know that C was designed a long time ago when there wasn't much knowledge about language design. I'm not trying to berate its original creators, I just think it's time to move on to more modern systems programming languages like Nim, Rust or Zig. That's why this criticism is from a modern perspective.
  p.notice I found 
    a(href="https://eev.ee/blog/2016/12/01/lets-stop-copying-c/") this article
    |  which explains many things much better than I, so please check it out. My article contains a few duplicates and some additional points.
  h2 Preprocessor
  p What's a better way of doing imports and macros than embedding another language with completely different syntax, which does naive text substitution, into your language? In order to avoid dangers which are not present in any sane import/macro systems, you have to do ugly hacks such as:
  ul
    li
      p Include guards
      pre
        code.
          #ifndef YOU_NEED_TO_MANUALLY_MAKE_SURE_THAT_YOUR_FILE_ISNT_INCLUDED_MULTIPLE_TIMES
          #define YOU_NEED_TO_MANUALLY_MAKE_SURE_THAT_YOUR_FILE_ISNT_INCLUDED_MULTIPLE_TIMES
          // your code here
          #endif
    li
      p The 
        code do { ... } while (0)
        |  thing to make sure that a macro can be used as a normal function
    li
      p Wrapping everything in parentheses to make a macro work like a normal function
      pre
        code.
          #define MAX(a, b) ((a) > (b) ? (a) : (b))
      p If any parentheses are left out, it results in counter-intuitive behavior. Actually, even with them it doesn't work like a normal function: the arguments will be evaluated as many times as they're in the macro body!
  h2 Braces &amp; Semicolons
  p See 
    a(href='braces-semicolons.html') Braces &amp; Semicolons
  h2 Syntax inconsistencies &amp; warts
  p Since many other languages (Java, C#, JavaScript, ...) have mindlessly copied most syntax from C, these mistakes have a profound effect on a whole family of languages.
  ul
    li All control structures that take a statement (if, while, for, switch) have the form of 
      code KEYWORD (SOMETHING) STATEMENT
      | . Except for the do-while loop, which for some reason has the form 
      code KEYWORD STATEMENT KEYWORD (SOMETHING);
      | . Totally different and including an extra semicolon.
      ul.qa
        li But it visually indicates that the condition is first checked after the statement!
        li Then why is a for loop written as 
          code for (INIT; CONDITION; STEP) STATEMENT
          |  rather than 
          code for (INIT; CONDITION) STATEMENT (STEP);
          | ? By the same logic, we should visually indicate that the step (usually increment) is first executed after the statement.
    li The choice to require an if/while condition to be wrapped in parentheses, rather than requiring the body to be wrapped in braces (as in Rust). Not only does this introduce syntactic noise, but it leads to subtle bugs if you mess up indentation:
      pre
        code.
          if (launch_button_pressed)
              check(missile); /* this was added in after we decided to make our missile system safer */
              launch(missile);
    li The for loop is just another way to write a while loop, instead of something actually useful like Python's 
      code for item in items:
      | .
    li The syntax for labels (including switch cases) is completely different from everything else. For consistency, it could be something like 
      code label (NAME) STATEMENT
      |  and 
      code case (VALUE) STATEMENT
      | .
  h2 Tooling
  ul
    li By default, the compilers don't have most warnings enabled. And it's very difficult to actually enable all warnings. 
      code -Wall
      |  enables only some warnings. What the fuck?
    li The default name for the compiled executable is 
      code a.out
      | , instead of being based on the source filename. So you need to do things like 
      code gcc my_awesome_program.c -o my_awesome_program
      | .
    li You need to specify the libraries you're using in the compilation command, instead of just putting them in the source file.
